package com.lhn.netty.nio;

/**
 * 分散和聚合
 *
 * @author lhn
 * @date 2025/05/27 09:59
 * @since 1.0.0
 **/

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * 分散（Scattering）将Channel中的数据读到多个Buffer中, 以次写入到
 * 聚合（Gathering）将多个Buffer的数据写入Channel 以次读出
 */
public class ScatteringAndGatherTest {

    public static void main(String[] args) throws Exception {
        // 使用 ServerSocketChannel  和 SocketChannel 网络
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 绑定端口到 socket 并启动
        serverSocketChannel.bind(new InetSocketAddress( 6666));

        // 创建buffer数组
        ByteBuffer[] byteBuffers = new ByteBuffer[2];
        byteBuffers[0] = ByteBuffer.allocate(5);
        byteBuffers[1] = ByteBuffer.allocate(3);

        // 等待客户端连接
        SocketChannel socketChannel = serverSocketChannel.accept();
        int messagesLength  = 8; // 8 个字节 从客户端接收到的消息长度
        while (true) {
            int byteRead = 0;
            while (byteRead < messagesLength) {
                long l = socketChannel.read(byteBuffers); // 将byteBuffer的数据读到socketChannel
                byteRead += l; // 累计读取的字节数
                System.out.println("byteRead = " + byteRead);
                // 使用流打印
                Arrays.asList(byteBuffers).stream().map(buffer -> "postion=" + buffer.position() + ", limit=" + buffer.limit())
                        .forEach(System.out::println);
            }

            // 读取之后，重置读写指针
            Arrays.asList(byteBuffers).stream().forEach(buffer -> buffer.flip());
            // 将数据读出显示到客户端
            long byteWrite = 0;
            while (byteWrite < messagesLength) {
                long l = socketChannel.write(byteBuffers); // 将byteBuffer的数据写到socketChannel
                System.out.println("byteWrite = " + byteWrite);
                byteWrite += l;
            }
            // 将所以的缓存数据清空
            Arrays.asList(byteBuffers).stream().forEach(buffer -> buffer.clear());
            System.out.println("byteRead = " + byteRead + ", byteWrite = " + byteWrite + ", messageLength = " + messagesLength);
        }

    }

}